#ifndef SQL_MCRECORDER_H
#define SQL_MCRECORDER_H

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlQueryModel>
#include <QSqlError>

#include <QMutex>
#include <QThread>
#include <QVector>
#include <QLinkedList>
#include <QQueue>
#include <QDebug>
#include <QTimer>
#include <QDate>

#include <QJsonValue>
#include "sql_mcdefine.h"
#include "exc_screen_config.h"

#include <math.h>

//#define _SQL_DEBUG_PRINT_   //打印debug信息到pte
//#define _QML_DEBUG_PRINT_
//#define _QML_FOCUS_REFURBISH_

enum _FactorRecordingEnum{
    ug=0,//机端电压
    ig, //机端电流
    il, //励磁电流
    usyn, //同步电压
    ugd,//自动给定
    igd,//手动给定
    uk, //控制信号
    p,
    q,
    f,
    us  //系统电压
};

class Sql_MCRecorder: public QThread
{
    Q_OBJECT
public:
    Sql_MCRecorder(Sql_MCDefine *i_sql_mcdefine);
    ~Sql_MCRecorder();

//    QQmlListProperty<QString> get_vecResultRecordToQml();
    //创建数据库并建立连接
    bool OpenDb(void);
    //关闭数据库
    void CloseDb(void);
    //是否成功开启
    bool IsOpenSuccess(void){
        return db.isOpen();
    }

    //********************* 传入语句查询 **********************
    //查询和显示结果-qml接口，1项、单个
    Q_INVOKABLE QJsonValue qml_queryTableOne(QString i_str);
    //查询和显示结果-qml接口，多行R、单列C
//    Q_INVOKABLE bool qml_queryTable1DRetBool(QString i_str);
//    Q_INVOKABLE QVector<QString> qml_getVecResult1D();
    Q_INVOKABLE QVector<QString> qml_queryTablenR1CRetVec(QString i_str);
    //查询和显示结果-qml接口，单行R、多列C
    Q_INVOKABLE QVector<QString> qml_queryTable1RnCRetVec(QString i_str);
    //查询和显示结果-qml接口，多行R，多列C
    Q_INVOKABLE bool qml_queryTable2DRetBool(QString i_str);
    Q_INVOKABLE QVector<QString> qml_getVecResult2D(unsigned int);
    Q_INVOKABLE int qml_getVecResult2DNum();
    Q_INVOKABLE QVector<QVector<QString>> qml_queryTable2DRetVec2D(QString i_str);
    Q_INVOKABLE QVector<QString> qml_queryTable2DRetVec1D(QString i_str);

    //********************* 特殊查询\修改 **********************
    //查询目前有几个数据项
    Q_INVOKABLE int qml_queryTableItemNum(QString i_tableName);
    //修改发电机参数
    Q_INVOKABLE void qml_setMotorFactor(QString i_str, int value);
    Q_INVOKABLE QJsonValue qml_getFactor(QString i_str);

    //********************* 查询内存中MC参数 **********************
    //查询数字量，根据mcdefine点表定义的define，返回有符号值/无符号值
    Q_INVOKABLE int qml_getRecordVal_toint16(int i_dec);
    Q_INVOKABLE unsigned int qml_getRecordVal_touint16(int i_dec);

    //********************* 查询内存中MC参数-联合数据库查询 **********************
    //查询单个位bit
    Q_INVOKABLE bool qml_getBitBool(QString i_prefixion, QString i_tableName, QString i_function);
    //查询MC参数，根据中文描述，返回有符号值
    Q_INVOKABLE int qml_getRecordVal_bystr_toint16(QString i_dec){
        return qml_getRecordVal_toint16(sql_mcdefine->cpp_queryTableOne(
                                         QString("SELECT dec FROM mc_define WHERE define='%1'").arg(i_dec)).toInt());
    }
    //查询MC参数，根据中文描述，返回无符号值
    Q_INVOKABLE int qml_getRecordVal_bystr_touint16(QString i_dec){
        return qml_getRecordVal_touint16(sql_mcdefine->cpp_queryTableOne(
                                         QString("SELECT dec FROM mc_define WHERE define='%1'").arg(i_dec)).toInt());
    }

    //********************* 查询内存中调节器参数 **********************
    Q_INVOKABLE int qml_getRegulatorVal_toint16(int i_dec);
    Q_INVOKABLE unsigned int qml_getRegulatorVal_touint16(int i_dec);

    //********************* 查询内存中调节器参数-跨数据库联合查询 **********************
    //查询MC参数，根据中文描述，返回有符号值
    Q_INVOKABLE int qml_getRegulatorVal_bystr_toint16(QString i_str){
        return qml_getRegulatorVal_toint16(sql_mcdefine->cpp_queryTableOne(
                                         QString("SELECT dec FROM reg_define WHERE define='%1'").arg(i_str)).toInt());
    }
    //查询MC参数，根据中文描述，返回无符号值
    Q_INVOKABLE int qml_getRegulatorVal_bystr_touint16(QString i_str){
        return qml_getRegulatorVal_touint16(sql_mcdefine->cpp_queryTableOne(
                                         QString("SELECT dec FROM reg_define WHERE define='%1'").arg(i_str)).toInt());
    }
    Q_INVOKABLE QString qml_getRegulatorVal_bystr_toRealStr(QString i_str){
        int t1 = qml_getRegulatorVal_toint16(sql_mcdefine->cpp_queryTableOne(
                                        QString("SELECT dec FROM reg_define WHERE define='%1'").arg(i_str)).toInt());
        int t = sql_mcdefine->cpp_queryTableOne(QString("SELECT pointLocation FROM reg_define WHERE define='%1'").arg(i_str)).toInt();
        return QString::number(t1/pow(10, t), 'f', t);
    }

    //********************* 报警状态处理 **********************
    //更新报警信息，并返回新增警报数量
    Q_INVOKABLE int qml_updateAlarmAndRetNum();
    Q_INVOKABLE void qml_updateAlarmAndSendMsg();

    //********************* 写入录波数据数据库 **********************
    struct _dataFIntStruct{
        QDateTime dateTime;
        int dataA[11];
        int dataB[11];
    };
    bool cpp_writeDataFToDb(QQueue<struct _dataFIntStruct> i_queueBak);

    //********************* 写入内存 **********************
    //封装的 寄存器 位写入
    void cpp_setRecordVal(int addr, int data);
    //处理modbus接收的数据
    void cpp_modbusRecFinish(QVector<quint16> t_vecQuint16);
    Q_INVOKABLE bool qml_getResetFlagConstantRecorder(){
        bool t = m_flagConstantRecorder;
        m_flagConstantRecorder = false;
        return t;
    }

    //********************* 保存用户权限状态 **********************
    int m_operatorMode;
    Q_INVOKABLE int qml_getOperaterMode(){return m_operatorMode;}
    Q_INVOKABLE void qml_setOperaterMode(int value){m_operatorMode=value;}

    //********************* 访问系统的操作 **********************
    //唤起软键盘
    Q_INVOKABLE void qml_arouseKeyboard(){
#if defined(Q_OS_WIN32)
#elif defined(Q_OS_LINUX)
        system("onboard &");
#endif
    }

    //5-对时
//    bool m_timeSynFlag;
    Q_INVOKABLE void qml_setTimeSynFlag(bool i){qml_setMotorFactor("timesyn", i);}
    Q_INVOKABLE bool qml_getTimeSynFlag(){
        QJsonValue t = qml_getFactor("timesyn");
        if(t=="NULL") {
            qml_queryTableOne("insert into motor_factor (name,value) VALUES ('timesyn',1)");
            return true;
        }
        else{
            if(t=="1") return true;
            else return false;
        }
    }
    bool cpp_setSystemTime()
    {
        int sec = qml_getRegulatorVal_touint16(0x48f0);
        int min = qml_getRegulatorVal_touint16(0x48f1);
        int hour = qml_getRegulatorVal_touint16(0x48f2);
        int date = qml_getRegulatorVal_touint16(0x48f3);
        int mont = qml_getRegulatorVal_touint16(0x48f4);
        int year = qml_getRegulatorVal_touint16(0x48f5);
        QDateTime dateTime(QDate(year, mont, date), QTime(hour, min, sec));
        int timeoffset = dateTime.secsTo(QDateTime().currentDateTime());
//        qDebug() << dateTime.toSecsSinceEpoch() << QDateTime().currentSecsSinceEpoch() - dateTime.toSecsSinceEpoch();
//        qDebug() << timeoffset << dateTime.secsTo(QDateTime().currentDateTimeUtc());
        if(qml_getTimeSynFlag() && abs(timeoffset)<3600*24*365 && abs(timeoffset) > 5)
            qml_setSystemTime(dateTime.toString("yyyy-MM-dd")+QString("T")+dateTime.toString("hh:mm:ss"));
        else return false;
        return true;
    }
    Q_INVOKABLE void qml_setSystemTime(QString timestr){
#if defined(Q_OS_WIN32)
#elif defined(Q_OS_LINUX)
        QString str = QString("echo \"tinnu\" | sudo -S date -s %1 &").arg(timestr);
        char*  ch;
        QByteArray ba = str.toLatin1();
        ch=ba.data();
        system(ch);
#endif
    }

public slots:
    //********************* 报警状态处理 **********************
    void SL_updateAlarmAndSendMsg();

    //********************* fdb录波数据嵌入 **********************
    void SL_insertFRecorderSQL();

signals:
    //********************* 向QML写完成发送信号 **********************
    //发送报警状态写完成信号
    void sn_sqlAlarmWriteFinish(QVector<QString>, QVector<QString>);

private:
    //********************* database句柄 **********************
    QSqlDatabase db;//用于建立和数据库的连接

    QVector<QVector<QString>> o_queryResult2D;

    //********************* 缓存modbus数据寄存器 **********************
    QVector<quint16> m_constantRecorder;    //0x63-0xC2
    QVector<quint16> m_regulatorRecorderA;   //0x4101-0x41EC
    QVector<quint16> m_regulatorRecorderB;   //0x5101-0x51EC
    QVector<quint16> m_regulatorRecorderTime;   //0x48f0-0x48f5
    bool m_flagConstantRecorder; //constantRecorder更新标志位

    //********************* 录波缓冲队列 **********************

//    QQueue<QString> m_dataFRecordingQueue;
    QQueue<struct _dataFIntStruct> m_dataFIntQueue;
    QQueue<struct _dataFIntStruct> m_dataFIntQueueBak;
    bool m_dataFEnableFlag; //报警录波状态
    bool m_dataFWriteFlag;  //写入标志
    quint32 m_dataFCounter;
    QMutex m_dataFOptMutex;

    QQueue<QString> m_dataTRecordingQueue;
    QMutex m_dataTRecorderMutex;

    //********************* mcdefine数据库句柄 **********************
    Sql_MCDefine *sql_mcdefine;

    //********************* QML宏定义配置 **********************
    bool qml_printFlag; //qml打印功能
    bool qml_refurbishFlag; //qml非焦点不刷新功能
    int m_recordWave; //1-不录波;2-警报时录波;3-一直录波(default);4-新警报到达时录波十分钟
//    QTimer *m_recordWaveAlarmMode;
    int m_recordTWave;

    void run() override;

public:
    Q_INVOKABLE bool qml_getPrintFlag(){return qml_printFlag;}
    Q_INVOKABLE bool qml_getRefurbishFlag(){return qml_refurbishFlag;}
    Q_INVOKABLE int qml_getRecordWaveFlag(){return m_recordWave;}
    Q_INVOKABLE void qml_setRecordWaveFlag(int t){m_recordWave=t;}
    Q_INVOKABLE int qml_getRecordTWaveFlag(){return m_recordTWave;}
    Q_INVOKABLE void qml_setRecordTWaveFlag(int t){m_recordTWave=t;}
};

struct _QuerySetBitContent
{
    int dec;
    int bit;
    QString define;
    QString explicate;
    QString reg;
    QString content;
    bool sorn;
};

struct _QuerySetBitContentSimple
{
    int dec;
    int bit;
    bool sorn;
    QDate date;
    QTime time;
    QString str;
};


#endif // SQL_MCRECORDER_H
